home *** CD-ROM | disk | FTP | other *** search
- #define ABOUT "usage: rep([flags],regular expression,replacement string,input text)\rrep XFCN v2.1 by Greg Anderson 14 Sept 1989\r"
- /*
- | | replace XFCN:
- | |
- | | Greg Anderson
- | | 24 Kerr Hall
- | | Social Sciences Computing
- | | University of California, Santa Cruz
- | | sirkm@ssyx
- | |
- | | Given a regular expresion and a replacement string, the
- | | 'replace' XFCN replaces all strings in the source text
- | | that match the regular expression.
- | |
- | | Example:
- | |
- | | put replace(reg exp,"replacement",bg fld "Info") into temp
- | |
- | |
- | | KNOWN BUGS:
- | |
- | | The resulting string cannot be more than 4K larger than the source
- | | string.
- |*/
-
- #include <MacTypes.h>
- #include <FileMgr.h>
- #include <SetUpA4.h>
- #include "HyperXCmd.h"
- #include "XCmdUtil.h"
- #include "regexp.h"
-
-
- /*-----------------------------------------------------------------
- | Function types
- -----------------------------------------------------------------*/
- pascal void main();
- void replace();
- void replacement();
- char searchline();
- char copyline();
- char advanceline();
-
- /*-----------------------------------------------------------------
- | This is the entry point to replace
- -----------------------------------------------------------------*/
- pascal void main(paramPtr)
- XCmdBlockPtr paramPtr;
- {
- char *list;
- int i;
-
- /*
- | | Fix up LSC
- */
- RememberA0();
- SetUpA4();
- /*
- | | Check for the propper number of parameters
- */
- if( (paramPtr->paramCount == 0) )
- {
- ReturnMsg(paramPtr,ABOUT);
- return;
- }
- if( (paramPtr->paramCount < 3) || (paramPtr->paramCount > 4) )
- {
- ReturnMsg(paramPtr,"Error in number of parameters.");
- return;
- }
-
- /*
- | | Move all parameters to top of heap and protect them
- */
- for (i=0;i<paramPtr->paramCount;i++)
- {
- MoveHHi(paramPtr->params[i]);
- HLock(paramPtr->params[i]);
- }
- /*
- | | Search through flags, if any were specified
- */
- regexp_flags = 0; /* From regexp.c */
- list = *(paramPtr->params[0]);
- if( (paramPtr->paramCount == 4) )
- {
- while( *list )
- {
- switch( *list++ )
- {
- case 'i': regexp_flags |= IGNORE;
- break;
- case 'm': regexp_flags |= MULTILINE;
- break;
- case 'f': regexp_flags |= FOLDEDLINE;
- break;
- case 'b': regexp_flags |= NOBREAKS;
- break;
- }
- }
- }
- /*
- | | Do the xcmd
- */
- replace(paramPtr);
-
- /*
- | | Unprotect the parameters so they can be freed by HyperCard
- */
- for (i=0;i<paramPtr->paramCount;i++)
- HUnlock(paramPtr->params[i]);
- /*
- | | The last thing to do before exiting:
- */
- RestoreA4();
- }
-
- /*-----------------------------------------------------------------
- | Main replace loop
- -----------------------------------------------------------------*/
- void replace(paramPtr)
- XCmdBlockPtr paramPtr;
- {
- Handle tempBuf;
- char *searchstring,
- *repstring,
- *in,
- *out;
- int i,
- regexpparam,
- replaceparam,
- textparam,
- searchlen;
- long handLen;
-
- regexpparam = (paramPtr->paramCount == 4);
- replaceparam = regexpparam + 1;
- textparam = replaceparam + 1;
- /*
- | |Create a temporary buffer about 4K larger than the input buffer.
- */
- handLen = GetHandleSize(paramPtr->params[textparam]) + 4200L;
- tempBuf = NewHandle((long)handLen);
- if( !tempBuf )
- {
- ReturnMsg(paramPtr,"Error allocating memory.");
- return;
- }
- MoveHHi(tempBuf);
- HLock(tempBuf);
-
- searchstring = *(paramPtr->params[regexpparam]);
- searchlen = greplen(&searchstring);
- repstring = *(paramPtr->params[replaceparam]);
- in = *(paramPtr->params[textparam]);
- out = *tempBuf;
-
- if( searchlen < 0 )
- {
- DisposHandle(tempBuf);
- ReturnMsg(paramPtr,"Error in search string.");
- return;
- }
-
- while( searchline(searchstring,repstring,&in,&out) );
-
- *out = 0;
- paramPtr->returnValue = tempBuf;
- }
-
- /*-----------------------------------------------------------------
- | Check if the current line contains the search pattern
- -----------------------------------------------------------------*/
- char searchline(searchstring,rep,in,out)
- char *searchstring,
- *rep,
- **in,
- **out;
- {
- char *initial,
- *start,
- *end,
- **start_p = &start,
- **end_p = &end;
-
- /*
- | | If there is nothing on the last line, then it is not a line.
- */
- if( **in == 0 ) return(0);
-
- if( regexp_flags & BEGINFLAG ) start_p = 0;
- if( regexp_flags & ENDFLAG ) end_p = 0;
-
- for(;;)
- {
- initial = *in;
- start = initial;
- if( find_regexp(searchstring,*in,start_p,end_p) )
- {
- /*
- | | Copy the beginning portion of the line (before
- | | the match) to the output buffer
- */
- while( initial < start )
- {
- *(*out)++ = *(*in)++;
- ++initial;
- }
- /*
- | | Insert the replacement string into the output buffer
- */
- replacement(rep,out);
- /*
- | | If this match was to the end of the line ('$' flag),
- | | then skip to the end of the input buffer line (which
- | | must be where the match ended) and copy an end-of-line
- | | marker to the output buffer.
- */
- if( !end_p )
- {
- *(*out)++ = '\r';
- return( advanceline(in) );
- }
- /*
- | | Skip past the portion of the input that was replaced
- */
- *in = end;
- /*
- | | If this match was from the beginning of the line
- | | ('^' flag), then copy everything in the input line
- | | after the match into the output buffer.
- */
- if( !start_p )
- return( copyline(in,out) );
- /*
- | | If neither '^' nor '$' were specified, but the match
- | | still went to the end of the line, add an end-of-line
- | | character to the output buffer and exit.
- | |
- | | If the pointer is not at the end of the line, then
- | | the rest of the input line will be checked for
- | | other possible matches.
- */
- if( end_of_line(end) )
- {
- *(*out)++ = '\r';
- return( *(*in)++ );
- }
- /*
- | | Prevent null regular expressions from looping
- | | infinitely--after every null match, skip over
- | | one input character (copying it to the output buffer)
- */
- if( !(*searchstring) ) *(*out)++ = *(*in)++;
- }
- else
- /*
- | | No matches on this line -- just copy the input
- | | line to the output buffer.
- */
- return( copyline(in,out) );
- }
- }
-
- /*-----------------------------------------------------------------
- | If a pattern is not found, copy the line to the output buffer
- -----------------------------------------------------------------*/
- char copyline(fieldptr,outputptr)
- char **fieldptr,
- **outputptr;
- {
- while( !end_of_line(*fieldptr) )
- {
- *(*outputptr)++ = *(*fieldptr)++;
- }
- *(*outputptr)++ = '\r';
- return( *(*fieldptr)++ );
- }
-
- /*-----------------------------------------------------------------
- | The pattern was found & replaced to the end of the line; advance
- | the pointer.
- -----------------------------------------------------------------*/
- char advanceline(fieldptr)
- char **fieldptr;
- {
- while( !end_of_line(*fieldptr) )
- (*fieldptr)++;
-
- return( *(*fieldptr)++ );
-
- }
-
- /*-----------------------------------------------------------------
- | If a pattern is found, copy the replacement to the output buffer
- -----------------------------------------------------------------*/
- void replacement(repstring,outputptr)
- char *repstring,
- **outputptr;
- {
- char c;
-
- while( (c = *repstring++) )
- *(*outputptr)++ = c;
- }
-